home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / uhren & terminkalender / time / sunclock / source / sun.c < prev    next >
C/C++ Source or Header  |  1996-04-07  |  6KB  |  242 lines

  1. /*-------------------------------------------------------------------------
  2.     SunClock
  3.  
  4.     Amiga version by Mark Waggoner, 
  5.     waggoner@ichips.intel.com or wagnell@PDaXcess.techbook.com
  6.     December 1991
  7.  
  8.     Sun.c
  9.     Routines to calculate and set the illumination mask for the sun clock
  10. -------------------------------------------------------------------------*/
  11. #include <time.h>
  12. #include <math.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <functions.h>
  16. #include <string.h>
  17. #include <graphics/gfx.h>
  18. #include "sunmath.h"
  19.  
  20. extern struct BitMap MapBitMap,IllumBitMap;
  21. extern UWORD DataWidth,DataHeight;
  22. extern WORD *Illum;
  23. extern void (*MapRefresh)(void);
  24. extern void (*TextRefresh)(void);
  25. extern char    loctimestr[],gmtimestr[];
  26.  
  27. /*-------------------------------------------------------------------------
  28.     Draw a horizontal line segment into the bitmap data
  29.     x0 must be less than x1 and both must be > 0
  30. -------------------------------------------------------------------------*/
  31. Segment(UBYTE *line,int x0,int x1)
  32. {
  33.     UBYTE *sp,*ep,sm,em;
  34.  
  35.     sp = line + x0/8;
  36.     ep = line + x1/8;
  37.     sm = 0xff>>(x0%8);
  38.     em = 0xff<<(7-x1%8);
  39.  
  40.     if (sp == ep) {
  41.         *sp = (sm & em);
  42.         return;
  43.     }
  44.  
  45.     *sp |= sm;
  46.     while (++sp<ep) *sp = 0xff;
  47.     *ep |= em;
  48. }
  49.  
  50. /*-------------------------------------------------------------------------
  51.     Set the illumination mask bitmap.
  52.     y is the row to set, 
  53.     noon is the midpoint of the mask
  54.     width is half the width of the mask
  55. -------------------------------------------------------------------------*/
  56. void
  57. SetIllum(int noon,int y,int width)
  58. {
  59.     UBYTE *line;
  60.     int x0,x1;
  61.  
  62.     if (width == 0) width = 1;
  63.     if (width < 0) return;
  64.  
  65.     if (y >= DataHeight) return;
  66.  
  67.     line = (UBYTE *)IllumBitMap.Planes[0] + (y * ((DataWidth + 15) / 16) * 2);
  68.  
  69.     x0 = noon - width;
  70.     x1 = noon + width;
  71.     if (x0<0) {
  72.         Segment(line,DataWidth+(x0%DataWidth),DataWidth-1);
  73.         x0 = 0;
  74.     }
  75.     if (x1 >= DataWidth) {
  76.         Segment(line,0,x1%DataWidth);
  77.         x1 = DataWidth-1;
  78.     }
  79.  
  80.     Segment(line,x0,x1);
  81. }
  82.  
  83. /*-------------------------------------------------------------------------
  84.     Project the suns illumination onto the bitmap mask
  85. -------------------------------------------------------------------------*/
  86. #define tableval(i,v)    if (i>=0 && i<DataHeight) { Illum[i] = ((v)==0) ? 1 : (v); }
  87.  
  88. static void
  89. ProjectIllumination(int noon,double dec)
  90. {
  91.     int i,j, ftf = 1;
  92.     int ilon, ilat, lilon, lilat, xt;
  93.     double m, x, y, z, th, lon, lat, s, c;
  94.  
  95.     for(i=0;i<DataHeight;i++)
  96.         Illum[i] = -1;
  97.  
  98.     /* Build transformation for declination */
  99.     dec = dtr(dec);
  100.     s = sin(-dec);
  101.     c = cos(-dec);
  102.  
  103.     /* Increment over a semicircle of illumination */
  104.  
  105.     for (th = -(PI / 2); th <= PI / 2 + 0.001; th += PI / TERMINC) {
  106.  
  107.         /* Transform the point through the declination rotation. */
  108.  
  109.         x = -s * sin(th);
  110.         y = cos(th);
  111.         z = c * sin(th);
  112.  
  113.         /* Transform the resulting co-ordinate through the
  114.            map projection to obtain screen co-ordinates. */
  115.  
  116.         lon = (y == 0 && x == 0) ? 0.0 : rtd(atan2(y, x));
  117.         lat = rtd(asin(z));
  118.  
  119.         ilat = DataHeight - (lat + 90) * (DataHeight / 180.0);
  120.         ilon = lon * (DataWidth / 360.0);
  121.  
  122.         if (ftf) {        /* First time.  Just save start co-ordinate. */
  123.             lilon = ilon;
  124.             lilat = ilat;
  125.             ftf = 0;
  126.         } else {
  127.             if (lilat == ilat) {    /* Set width */
  128.                 j = (DataHeight - 1) - ilat;
  129.                 tableval(j,ilon);
  130.             } else {                /* interpolate intermediate points */
  131.                 m = ((double) (ilon - lilon)) / (ilat - lilat);
  132.                 for (i = lilat; i != ilat; i += sgn(ilat - lilat)) {
  133.                     xt = lilon + floor((m * (i - lilat)) + 0.5);
  134.                     j = (DataHeight - 1) - i;
  135.                     tableval(j,xt);
  136.                 }
  137.             }
  138.             lilon = ilon;
  139.             lilat = ilat;
  140.         }
  141.     }
  142.  
  143.     /* Now tweak the widths to generate full illumination for
  144.        the correct pole. */
  145.  
  146.     if (dec < 0.0) {
  147.         ilat = DataHeight - 1;
  148.         lilat = -1;
  149.     } else {
  150.         ilat = 0;
  151.         lilat = 1;
  152.     }
  153.  
  154.     for (i = ilat; i != DataHeight / 2; i += lilat) {
  155.         if (Illum[i] != -1) {
  156.             while (1) {
  157.                 tableval(i,DataWidth/2);
  158.                 if (i == ilat)
  159.                     break;
  160.                 i -= lilat;
  161.             }
  162.             break;
  163.         }
  164.     }
  165.  
  166.     for(i=0;i<DataHeight;i++)
  167.         SetIllum(noon,i,Illum[i]);
  168.  
  169. }
  170.  
  171. /*-------------------------------------------------------------------------
  172.     Update the illumination if it has been long enough since the
  173.     last update.
  174. -------------------------------------------------------------------------*/
  175. void
  176. UpdateImages(int force)
  177. {
  178.     time_t            timeval;
  179.     static time_t    lasttime = 0;
  180.     struct tm        lt,*ct;
  181.     double            jt,gt;
  182.     double            sunra,sundec,sunrv,sunlong;
  183.     double            lastdec;
  184.     double            a;
  185.     int                xl;
  186.     static int        lastxl = -1;
  187.     LONG            sec0,mic0,sec1,mic1;
  188.     char            *tz;
  189.  
  190.     /* Find out what time it is */
  191.     time(&timeval);
  192.     lt = *localtime(&timeval);
  193.     ct = gmtime(&timeval);
  194.     if (!ct) ct = <
  195.     jt = jtime(ct);
  196.  
  197.     if (tz = getenv("TZ")) {
  198.         strncpy(loctimestr,tz,3);
  199.         loctimestr[3] = ':';
  200.         loctimestr[4] = ' ';
  201.         loctimestr[5] = '\0';
  202.         strcat(loctimestr,asctime(<));
  203.         loctimestr[strlen(loctimestr)-1] = '\0';
  204.     }
  205.     else
  206.         strcpy(loctimestr,"TZ Environment variable not set!");
  207.  
  208.     strcpy(gmtimestr,"GMT: ");
  209.     strcat(gmtimestr,asctime(ct));
  210.     gmtimestr[strlen(gmtimestr)-1] = '\0';
  211.  
  212.     TextRefresh();
  213.  
  214.     if ((timeval > lasttime) && ((timeval - lasttime) < 60) && !force) return;
  215.     lasttime = timeval;
  216.  
  217.     sunpos(jt, 0, &sunra, &sundec, &sunrv, &sunlong);
  218.     gt = gmst(jt);
  219.  
  220. /*    printf("RA: %g  DEC: %g  RV: %g  LONG: %g\n",sunra,sundec,sunrv,sunlong); */
  221.  
  222.     a = 180.0 + (sunra - (gt * 15));
  223.     sunlong = fixangle(a);
  224.     xl = sunlong * ((double) DataWidth / 360.0);
  225.  
  226.     /* If the subsolar point has moved at least one pixel, update
  227.        the illuminated area on the screen.    */
  228.  
  229.     if ((lastxl != xl) || (fabs(sundec - lastdec) > 5) || force) {
  230.         BltClear((char *)IllumBitMap.Planes[0],
  231.                     ((DataWidth+15)/16)*2*DataHeight,1);
  232.         ProjectIllumination(xl,sundec);
  233.  
  234.         BltBitMap(&MapBitMap,0,0,&IllumBitMap,0,0,
  235.                 DataWidth,DataHeight,0x60,0x01,0);
  236.  
  237.         (*MapRefresh)();
  238.         lastxl = xl;
  239.         lastdec = sundec;
  240.     }
  241. }
  242.